﻿using Magicodes.IE.Core;
using Microsoft.Extensions.Configuration;
using PHMEE.DTOS.StatusMonitor;
using PHMEE.IServices.StatusMonitor;
using PHMEE.PHM.Algorithms.Basic;
using PHMEE.TDengineInfrastructure;
using PHMEE.ToolKits;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TDengine.Data.Client;
using Volo.Abp.Domain.Repositories;
using static PHMEE.PHMEEAdminPermissions;

namespace PHMEE.Services.StatusMonitor
{
    public class SpectralAnalysisAppService : PHMEEAppService, ISpectralAnalysisAppService
    {
        private readonly ITDConnectionFactory iTDConnectionFactory;
        private readonly IPointRepository pointRepository;
        private readonly IVibChannelParaRepository vibChannelParaRepository;
        private readonly IRepository<Threshold, Guid> thresholdRepository;
        private readonly IRepository<Category, Guid> categoryRepository;
        private readonly AccToVelAlg accToVelAlg;
        private readonly FilterEnvelopeAlg filterEnvelopeAlg;
        private readonly FftAlg fftAlg;
        private readonly CepstrumAlg cepstrumAlg;

        public SpectralAnalysisAppService(ITDConnectionFactory iTDConnectionFactory, IPointRepository pointRepository, IVibChannelParaRepository vibChannelParaRepository, IRepository<Threshold, Guid> thresholdRepository, IRepository<Category, Guid> categoryRepository, AccToVelAlg accToVelAlg, FilterEnvelopeAlg filterEnvelopeAlg, FftAlg fftAlg, CepstrumAlg cepstrumAlg)
        {

            this.iTDConnectionFactory = iTDConnectionFactory;
            this.pointRepository = pointRepository;
            this.vibChannelParaRepository = vibChannelParaRepository;
            this.thresholdRepository = thresholdRepository;
            this.categoryRepository = categoryRepository;
            this.accToVelAlg = accToVelAlg;
            this.filterEnvelopeAlg = filterEnvelopeAlg;
            this.fftAlg = fftAlg;
            this.cepstrumAlg = cepstrumAlg;
        }


        /// <summary>
        /// 时域-加速度
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel> GetChartTimeAcceleration(Guid VesselId, ChartInput input)
        {
            PhMEEChartModel phmeeChartModel = new(PhmeeEchartUnit.MS);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                    // 单位s 需要转换成ms *1000
                    var period = syspara.SamplingFrequency != 0 ? (syspara.SamplingPoint / syspara.SamplingFrequency) * 1000 : 0;
                    var arrSource = await GetTdEngineSourceDataContent(VesselId, input);
                    var perms = period / arrSource.Length;
                    for (var i = 0; i < arrSource.Length; i++)
                    {
                        string xdata = $"{perms * (i + 1)}";
                        phmeeChartModel.XData.Add(xdata);
                        phmeeChartModel.YData.Add(arrSource[i]);
                    }
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 时域-速度
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel> GetChartTimeSpeed(Guid VesselId, ChartInput input)
        {
            PhMEEChartModel phmeeChartModel = new(PhmeeEchartUnit.MS);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.MMS);
                    // 单位s 需要转换成ms *1000
                    var period = syspara.SamplingFrequency != 0 ? (syspara.SamplingPoint / syspara.SamplingFrequency) * 1000 : 0;
                    var arrSource = await GetTdEngineSourceDataContent(VesselId, input);
                    // 调用接口算法获取速度
                    AccToVelResponse response = await accToVelAlg.AccToVelAsync(arrSource, syspara.SamplingFrequency, syspara.VelLowerFrq);
                    var arr = response.VelData.ToArray();
                    var perms = period / arr.Length;
                    for (var i = 0; i < arr.Length; i++)
                    {
                        string xdata = $"{perms * (i + 1)}";
                        phmeeChartModel.XData.Add(xdata);
                        phmeeChartModel.YData.Add(arr[i]);
                    }
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 时域-包络
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel> GetChartTimeEnvelope(Guid VesselId, ChartInput input)
        {
            PhMEEChartModel phmeeChartModel = new(PhmeeEchartUnit.MS);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                    // 单位s 需要转换成ms *1000
                    var period = syspara.SamplingFrequency != 0 ? (syspara.SamplingPoint / syspara.SamplingFrequency) * 1000 : 0;
                    var arrSource = await GetTdEngineSourceDataContent(VesselId, input);
                    // 调用接口算法获取速度
                    FilterEnvelopeResponse response = await filterEnvelopeAlg.FilterEnvelopeAsync(arrSource, syspara.SamplingFrequency);
                    var arr = response.At.ToArray();
                    var perms = period / arr.Length;
                    for (var i = 0; i < arr.Length; i++)
                    {
                        string xdata = $"{perms * (i + 1)}";
                        phmeeChartModel.XData.Add(xdata);
                        phmeeChartModel.YData.Add(arr[i]);
                    }
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 频域-加速度
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel<float, float>> GetChartFrequencyAcceleration(Guid VesselId, ChartInput input)
        {
            PhMEEChartModel<float, float> phmeeChartModel = new(PhmeeEchartUnit.HZ);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                    var arrSource = await GetTdEngineSourceDataContent(VesselId, input);
                    // 调用接口算法获取加速度幅值和频率轴
                    FftResponse response = await fftAlg.FftAsync(arrSource, syspara.SamplingFrequency);
                    var arrX = response.SingleSidedFrequencies.ToArray();
                    var arrY = response.SingleSidedFhat.ToArray();
                    phmeeChartModel.XData.AddRange(arrX);
                    phmeeChartModel.YData.AddRange(arrY);
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 频域-速度
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel<float, float>> GetChartFrequencySpeed(Guid VesselId, ChartInput input)
        {
            PhMEEChartModel<float, float> phmeeChartModel = new(PhmeeEchartUnit.HZ);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.MMS);
                    var arrSource = await GetTdEngineSourceDataContent(VesselId, input);
                    //调用接口算法
                    AccToVelResponse responseAcc = await accToVelAlg.AccToVelAsync(arrSource, syspara.SamplingFrequency, syspara.VelLowerFrq);
                    var arr = responseAcc.VelData.ToArray();
                    FftResponse responseFFT = await fftAlg.FftAsync(arr, syspara.SamplingFrequency);
                    phmeeChartModel.XData.AddRange(responseFFT.SingleSidedFrequencies);
                    phmeeChartModel.YData.AddRange(responseFFT.SingleSidedFhat);
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 包络-加速度
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel<float, float>> GetChartEnvelopeAccleration(Guid VesselId, ChartInput input)
        {
            PhMEEChartModel<float, float> phmeeChartModel = new(PhmeeEchartUnit.HZ);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                    var arrSource = await GetTdEngineSourceDataContent(VesselId, input);
                    // 调用接口算法获取速度
                    FilterEnvelopeResponse response = await filterEnvelopeAlg.FilterEnvelopeAsync(arrSource, syspara.SamplingFrequency);
                    var arrX = response.SingleSidedFreq.ToArray();
                    var arrY = response.SingleSidedAm.ToArray();
                    phmeeChartModel.XData.AddRange(arrX);
                    phmeeChartModel.YData.AddRange(arrY);
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 倒谱-加速度
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel<float, float>> GetChartCepstrumAcceleration(Guid VesselId, ChartInput input)
        {
            PhMEEChartModel<float, float> phmeeChartModel = new(PhmeeEchartUnit.MS);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                    var arrSource = await GetTdEngineSourceDataContent(VesselId, input);
                    CepstrumResponse response = await cepstrumAlg.CepstrumAsync(arrSource, syspara.SamplingFrequency);
                    var arrX = response.SingleSidedQuefrency.ToArray();
                    var arrY = response.SingleSidedCepstrum.ToArray();
                    phmeeChartModel.XData.AddRange(arrX);
                    phmeeChartModel.YData.AddRange(arrY);
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 趋势-加速度-有效值
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel<string, object>> GetChartTrendAccelerationValid(Guid VesselId, ChartInputTrend input)
        {
            List<WaveDataFeature> list = await GetTdEnginePointFeatureData(VesselId, input);
            PhMEEChartModel<string, object> phmeeChartModel = new(PhmeeEchartUnit.NONE);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            if (point != null)
            {
                phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                phmeeChartModel.Properties = await GetThresholdValues(point.Id);
            }
            phmeeChartModel.XData.AddRange(list.Select(item => item.TimeStamp.PhmeeToFriendlyDateTimeString()));
            phmeeChartModel.YData.AddRange(list.Select(item => item.TransformAccValid()));
            return phmeeChartModel;
        }

        /// <summary>
        /// 趋势-加速度-平均峰值
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel<string, object>> GetChartTrendAccelerationAverage(Guid VesselId, ChartInputTrend input)
        {
            List<WaveDataFeature> list = await GetTdEnginePointFeatureData(VesselId, input);
            PhMEEChartModel<string, object> phmeeChartModel = new(PhmeeEchartUnit.NONE);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            if (point != null)
            {
                phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                phmeeChartModel.Properties = await GetThresholdValues(point.Id);
            }
            phmeeChartModel.XData.AddRange(list.Select(item => item.TimeStamp.PhmeeToFriendlyDateTimeString()));
            phmeeChartModel.YData.AddRange(list.Select(item => item.TransformAccAccAvgPeak()));
            return phmeeChartModel;
        }

        /// <summary>
        /// 趋势-速度-有效值
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel<string, object>> GetChartTrendSpeedValid(Guid VesselId, ChartInputTrend input)
        {
            List<WaveDataFeature> list = await GetTdEnginePointFeatureData(VesselId, input);
            PhMEEChartModel<string, object> phmeeChartModel = new(PhmeeEchartUnit.NONE);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            if (point != null)
            {
                phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.MMS);
                phmeeChartModel.Properties = await GetThresholdValues(point.Id);
            }
            phmeeChartModel.XData.AddRange(list.Select(item => item.TimeStamp.PhmeeToFriendlyDateTimeString()));
            phmeeChartModel.YData.AddRange(list.Select(item => item.TransformVelRms()));
            return phmeeChartModel;
        }

        /// <summary>
        /// 趋势-包络-平均峰值
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PhMEEChartModel<string, object>> GetChartTrendEnvelopeAverage(Guid VesselId, ChartInputTrend input)
        {
            List<WaveDataFeature> list = await GetTdEnginePointFeatureData(VesselId, input);
            PhMEEChartModel<string, object> phmeeChartModel = new(PhmeeEchartUnit.NONE);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            if (point != null)
            {
                phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                phmeeChartModel.Properties = await GetThresholdValues(point.Id);
            }
            phmeeChartModel.XData.AddRange(list.Select(item => item.TimeStamp.PhmeeToFriendlyDateTimeString()));
            phmeeChartModel.YData.AddRange(list.Select(item => item.TransformAccEnvAvgPeak()));
            return phmeeChartModel;
        }


        /// <summary>
        /// 时域-加速度-最新一条数据
        /// </summary>
        /// <returns></returns>
        public async Task<PhMEEChartModel> GetChartTimeTdEngineSourceValueNewest(Guid VesselId, ChartInputNewest input)
        {
            PhMEEChartModel phmeeChartModel = new(PhmeeEchartUnit.MS);
            Point point = await pointRepository.PhmeeGetById(input.PointId);
            SysPara syspara = await vibChannelParaRepository.GetByVibChannelPara(input.PointId);
            if (point != null && syspara != null)
            {
                try
                {
                    phmeeChartModel.YDataUnit = PHMEECoreHelper.PhmeeGetDescription(PhmeeEchartUnit.G);
                    // 单位s 需要转换成ms *1000
                    var period = syspara.SamplingFrequency != 0 ? (syspara.SamplingPoint / syspara.SamplingFrequency) * 1000 : 0;
                    var arrSource = await GetTdEngineSourceDataContentNewest(VesselId, input);
                    var perms = period / arrSource.Length;
                    for (var i = 0; i < arrSource.Length; i++)
                    {
                        string xdata = $"{perms * (i + 1)}";
                        phmeeChartModel.XData.Add(xdata);
                        phmeeChartModel.YData.Add(arrSource[i]);
                    }
                }
                catch (Exception ex)
                {
                    phmeeChartModel.Info = ex.Message;
                    return phmeeChartModel;
                }
            }
            return phmeeChartModel;
        }

        /// <summary>
        /// 特征值
        /// </summary>
        /// <returns></returns>
        public async Task<List<WaveDataFeature>> GetTdEngineFeatureValue(Guid VesselId, ChartInputTrend input)
        {
            var list = await GetTdEnginePointFeatureData(VesselId, input);
            return list;
        }

        /// <summary>
        /// 获取阈值配置相关信息
        /// </summary>
        /// <param name="pointId"></param>
        /// <returns></returns>
        private async Task<ChartThreshold> GetThresholdValues(Guid pointId)
        {
            // 获取定义的阈值分类
            var category速度有效值 = await categoryRepository.FirstOrDefaultAsync(item => item.LimitPara == LimitParaEnum.EffectiveSpeed);
            var category加速度峰值 = await categoryRepository.FirstOrDefaultAsync(item => item.LimitPara == LimitParaEnum.PeakAcceleration);
            var category加速度有效值 = await categoryRepository.FirstOrDefaultAsync(item => item.LimitPara == LimitParaEnum.EffectiveAcc);

            //获取定义的阈值
            var threshold速度有效值 = await thresholdRepository.FirstOrDefaultAsync(item => item.PointId == pointId && item.LimitPara == LimitParaEnum.EffectiveSpeed && item.isEnable && !item.IsDeleted);
            var threshold加速度峰值 = await thresholdRepository.FirstOrDefaultAsync(item => item.PointId == pointId && item.LimitPara == LimitParaEnum.PeakAcceleration && item.isEnable && !item.IsDeleted);
            var threshold加速度有效值 = await thresholdRepository.FirstOrDefaultAsync(item => item.PointId == pointId && item.LimitPara == LimitParaEnum.EffectiveAcc && item.isEnable && !item.IsDeleted);

            ChartThreshold model = new ChartThreshold();

            model.VelValidFirstThreshold = threshold速度有效值?.FirstThreshold;
            model.VelValidSecondThreshold = threshold速度有效值?.SecondThreshold;
            model.VelValidThirdThreshold = threshold速度有效值?.ThirdThreshold;
            model.VelValidFourthThreshold = threshold速度有效值?.FourthThreshold;

            model.AccAvgFirstThreshold = threshold加速度峰值?.FirstThreshold;
            model.AccAvgSecondThreshold = threshold加速度峰值?.SecondThreshold;
            model.AccAvgThirdThreshold = threshold加速度峰值?.ThirdThreshold;
            model.AccAvgFourthThreshold = threshold加速度峰值?.FourthThreshold;

            model.AccValidFirstThreshold = threshold加速度有效值?.FirstThreshold;
            model.AccValidSecondThreshold = threshold加速度有效值?.SecondThreshold;
            model.AccValidThirdThreshold = threshold加速度有效值?.ThirdThreshold;
            model.AccValidFourthThreshold = threshold加速度有效值?.FourthThreshold;

            return model;

        }



        #region Echart数据源

        #region 源数据

        /// <summary>
        /// 获取源数据content
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<float[]> GetTdEngineSourceDataContent(Guid VesselId, ChartInput input)
        {
            List<WaveDataSource> list = input.Type switch
            {
                ChartEnum.Normal => await GetTdEnginePointSourceDataNormal(VesselId, input),
                ChartEnum.Alarm => await GetTdEnginePointSourceDataAlarm(VesselId, input),
                _ => new List<WaveDataSource>()
            };
            var arr = list.SelectMany(item => item.DataContent).ToArray();
            float[] arrFloat = ParseTdEngineContent(arr);
            return arrFloat;
        }

        /// <summary>
        /// 获取源数据content最新一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<float[]> GetTdEngineSourceDataContentNewest(Guid VesselId, ChartInputNewest input)
        {
            ChartInput chartInput = new ChartInput();
            chartInput.PointId = input.PointId;
            chartInput.Type = input.Type;

            WaveDataSource dataSourceNewest = new WaveDataSource();

            switch (chartInput.Type)
            {
                case ChartEnum.Normal:
                    dataSourceNewest = await GetTdEnginePointSourceDataNormalNewest(VesselId, input);
                    break;
                case ChartEnum.Alarm:
                    dataSourceNewest = await GetTdEnginePointSourceDataAlarmNewest(VesselId, input);
                    break;
            }

            float[] arrFloat = [];
            if (DateTime.TryParse(dataSourceNewest?.TimeStamp.PhmeeToFriendlyDateTimeString(), out DateTime endtime))
            {
                chartInput.EndTime = endtime;
                arrFloat = await GetTdEngineSourceDataContent(VesselId, chartInput);
            }
            return arrFloat;
        }

        /// <summary>
        /// TdEngine字节数组转换方法
        /// </summary>
        /// <param name="arr"></param>
        /// <returns></returns>
        private float[] ParseTdEngineContent(byte[] arr)
        {
            int floatArrLength = arr.Length / 4;
            float[] arrFloat = new float[floatArrLength];
            for (int i = 0; i < floatArrLength; i++)
            {
                arrFloat[i] = BitConverter.ToSingle(arr, i * 4);
            }
            return arrFloat;
        }


        /// <summary>
        /// 获取某个测点的TDEngine表源数据-全部
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<List<WaveDataSource>> GetTdEnginePointSourceData(Guid VesselId, ChartInput input)
        {
            List<WaveDataSource> list = [.. await GetTdEnginePointSourceDataNormal(VesselId, input), .. await GetTdEnginePointSourceDataAlarm(VesselId, input)];
            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list;
        }

        /// <summary>
        /// 获取某个测点的TDEngine表源数据-正常
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<List<WaveDataSource>> GetTdEnginePointSourceDataNormal(Guid VesselId, ChartInput input)
        {
            string dbName = PhmeeConst.GetDbName(DbPrefixEnum.Vb, VesselId);
            string sqlNormalSuper = $"select 1 from {dbName}.wavedata_normal where pointid='{input.PointId}';";
            string sqlNormal = $"select *,chno,id,pointid from {dbName}.wdn_{input.PointFormatGuid()} where ts >= '{input.EndTime.PhmeeToUtcFormatDateTimeString()}' and ts < '{input.EndTime.AddSeconds(1).PhmeeToUtcFormatDateTimeString()}'  order by ts asc ;";
            List<WaveDataSource> list = new List<WaveDataSource>();
            using (TDengineConnection dbConnection = iTDConnectionFactory.GetConnection())
            {
                bool resultNormalFlag = true;
                using (DbCommand commandNormalExist = dbConnection.CreateCommand())
                {
                    commandNormalExist.CommandText = sqlNormalSuper;
                    var resultNormal = await commandNormalExist.ExecuteScalarAsync();
                    resultNormalFlag = Convert.ToBoolean(resultNormal);
                }
                if (resultNormalFlag)
                {
                    using (DbCommand commandNormal = dbConnection.CreateCommand())
                    {
                        commandNormal.CommandText = sqlNormal;
                        using (DbDataReader readerNormal = await commandNormal.ExecuteReaderAsync())
                        {
                            while (await readerNormal.ReadAsync())
                            {
                                WaveDataSource waveDataNormal = new WaveDataSource();
                                waveDataNormal.Type = ChartEnum.Normal;
                                waveDataNormal.TimeStamp = readerNormal.GetPhmeeTdEngineValue<DateTime>("ts");
                                waveDataNormal.DataContent = readerNormal.GetPhmeeTdEngineValue<byte[]>("data_content");
                                waveDataNormal.ChNo = readerNormal.GetPhmeeTdEngineValue<int>("chno");
                                waveDataNormal.Id = Guid.Parse(Encoding.UTF8.GetString(readerNormal.GetPhmeeTdEngineValue<byte[]>("id")));
                                waveDataNormal.PointId = Guid.Parse(Encoding.UTF8.GetString(readerNormal.GetPhmeeTdEngineValue<byte[]>("pointid")));
                                list.Add(waveDataNormal);
                            }
                        }
                    }
                }
            }

            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list;
        }

        /// <summary>
        /// 获取某个测点的TDEngine表源数据-报警
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<List<WaveDataSource>> GetTdEnginePointSourceDataAlarm(Guid VesselId, ChartInput input)
        {
            string dbName = PhmeeConst.GetDbName(DbPrefixEnum.Vb, VesselId);
            string sqlAlarmSuper = $"select 1 from {dbName}.wavedata_alarm where pointid='{input.PointId}';";
            string sqlAlarm = $"select *,chno,id,pointid from {dbName}.wda_{input.PointFormatGuid()} where ts >= '{input.EndTime.PhmeeToUtcFormatDateTimeString()}' and ts < '{input.EndTime.AddSeconds(1).PhmeeToUtcFormatDateTimeString()}'  order by ts asc ;";
            List<WaveDataSource> list = new List<WaveDataSource>();
            using (TDengineConnection dbConnection = iTDConnectionFactory.GetConnection())
            {
                bool resultAlarmFlag = true;
                using (DbCommand commandAlarmExist = dbConnection.CreateCommand())
                {
                    commandAlarmExist.CommandText = sqlAlarmSuper;
                    var resultAlarm = await commandAlarmExist.ExecuteScalarAsync();
                    resultAlarmFlag = Convert.ToBoolean(resultAlarm);
                }
                if (resultAlarmFlag)
                {
                    using (DbCommand commandAlarm = dbConnection.CreateCommand())
                    {
                        commandAlarm.CommandText = sqlAlarm;
                        using (DbDataReader readerAlarm = await commandAlarm.ExecuteReaderAsync())
                        {
                            while (await readerAlarm.ReadAsync())
                            {
                                WaveDataSource waveDataAlarm = new WaveDataSource();
                                waveDataAlarm.Type = ChartEnum.Alarm;
                                waveDataAlarm.TimeStamp = readerAlarm.GetPhmeeTdEngineValue<DateTime>("ts");
                                waveDataAlarm.DataContent = readerAlarm.GetPhmeeTdEngineValue<byte[]>("data_content");
                                waveDataAlarm.ChNo = readerAlarm.GetPhmeeTdEngineValue<int>("chno");
                                waveDataAlarm.Id = Guid.Parse(Encoding.UTF8.GetString(readerAlarm.GetPhmeeTdEngineValue<byte[]>("id")));
                                waveDataAlarm.PointId = Guid.Parse(Encoding.UTF8.GetString(readerAlarm.GetPhmeeTdEngineValue<byte[]>("pointid")));
                                list.Add(waveDataAlarm);
                            }
                        }
                    }

                }
            }

            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list;
        }

        /// <summary>
        /// 获取某个测点的TDEngine表源数据最新一条数据-正常-部分数据中某一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<WaveDataSource> GetTdEnginePointSourceDataNormalNewest(Guid VesselId, ChartInputNewest input)
        {
            string dbName = PhmeeConst.GetDbName(DbPrefixEnum.Vb, VesselId);
            string sqlNormalSuper = $"select 1 from {dbName}.wavedata_normal where pointid='{input.PointId}';";
            string sqlNormal = $"select *,chno,id,pointid from {dbName}.wdn_{input.PointFormatGuid()}  order by ts desc limit 1 ;";
            List<WaveDataSource> list = new List<WaveDataSource>();
            using (TDengineConnection dbConnection = iTDConnectionFactory.GetConnection())
            {
                bool resultNormalFlag = true;
                using (DbCommand commandNormalExist = dbConnection.CreateCommand())
                {
                    commandNormalExist.CommandText = sqlNormalSuper;
                    var resultNormal = await commandNormalExist.ExecuteScalarAsync();
                    resultNormalFlag = Convert.ToBoolean(resultNormal);
                }
                if (resultNormalFlag)
                {
                    using (DbCommand commandNormal = dbConnection.CreateCommand())
                    {
                        commandNormal.CommandText = sqlNormal;
                        using (DbDataReader readerNormal = await commandNormal.ExecuteReaderAsync())
                        {
                            while (await readerNormal.ReadAsync())
                            {
                                WaveDataSource waveDataNormal = new WaveDataSource();
                                waveDataNormal.Type = ChartEnum.Normal;
                                waveDataNormal.TimeStamp = readerNormal.GetPhmeeTdEngineValue<DateTime>("ts");
                                waveDataNormal.DataContent = readerNormal.GetPhmeeTdEngineValue<byte[]>("data_content");
                                waveDataNormal.ChNo = readerNormal.GetPhmeeTdEngineValue<int>("chno");
                                waveDataNormal.Id = Guid.Parse(Encoding.UTF8.GetString(readerNormal.GetPhmeeTdEngineValue<byte[]>("id")));
                                waveDataNormal.PointId = Guid.Parse(Encoding.UTF8.GetString(readerNormal.GetPhmeeTdEngineValue<byte[]>("pointid")));
                                list.Add(waveDataNormal);
                            }
                        }
                    }
                }
            }

            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list.FirstOrDefault();
        }


        /// <summary>
        /// 获取某个测点的TDEngine表源数据最新一条数据-报警-部分数据中某一条
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<WaveDataSource> GetTdEnginePointSourceDataAlarmNewest(Guid VesselId, ChartInputNewest input)
        {
            string dbName = PhmeeConst.GetDbName(DbPrefixEnum.Vb, VesselId);
            string sqlAlarmSuper = $"select 1 from {dbName}.wavedata_alarm where pointid='{input.PointId}';";
            string sqlAlarm = $"select *,chno,id,pointid from {dbName}.wda_{input.PointFormatGuid()}  order by ts desc limit 1 ;";
            List<WaveDataSource> list = new List<WaveDataSource>();
            using (TDengineConnection dbConnection = iTDConnectionFactory.GetConnection())
            {
                bool resultAlarmFlag = true;
                using (DbCommand commandAlarmExist = dbConnection.CreateCommand())
                {
                    commandAlarmExist.CommandText = sqlAlarmSuper;
                    var resultAlarm = await commandAlarmExist.ExecuteScalarAsync();
                    resultAlarmFlag = Convert.ToBoolean(resultAlarm);
                }
                if (resultAlarmFlag)
                {
                    using (DbCommand commandAlarm = dbConnection.CreateCommand())
                    {
                        commandAlarm.CommandText = sqlAlarm;
                        using (DbDataReader readerAlarm = await commandAlarm.ExecuteReaderAsync())
                        {
                            while (await readerAlarm.ReadAsync())
                            {
                                WaveDataSource waveDataAlarm = new WaveDataSource();
                                waveDataAlarm.Type = ChartEnum.Alarm;
                                waveDataAlarm.TimeStamp = readerAlarm.GetPhmeeTdEngineValue<DateTime>("ts");
                                waveDataAlarm.DataContent = readerAlarm.GetPhmeeTdEngineValue<byte[]>("data_content");
                                waveDataAlarm.ChNo = readerAlarm.GetPhmeeTdEngineValue<int>("chno");
                                waveDataAlarm.Id = Guid.Parse(Encoding.UTF8.GetString(readerAlarm.GetPhmeeTdEngineValue<byte[]>("id")));
                                waveDataAlarm.PointId = Guid.Parse(Encoding.UTF8.GetString(readerAlarm.GetPhmeeTdEngineValue<byte[]>("pointid")));
                                list.Add(waveDataAlarm);
                            }
                        }
                    }

                }
            }

            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list.FirstOrDefault();
        }


        #endregion

        #region 特征值

        /// <summary>
        /// 获取某个测点的TDEngine表源数据特征值-全部
        /// </summary>
        /// <returns></returns>
        private async Task<List<WaveDataFeature>> GetTdEnginePointFeatureData(Guid VesselId, ChartInputTrend input)
        {
            List<WaveDataFeature> list = [.. await GetTdEnginePointFeatureDataNormal(VesselId, input), .. await GetTdEnginePointFeatureDataAlarm(VesselId, input)];

            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list;
        }

        /// <summary>
        /// 获取某个测点的TDEngine表源数据特征值-正常
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<List<WaveDataFeature>> GetTdEnginePointFeatureDataNormal(Guid VesselId, ChartInputTrend input)
        {
            string dbName = PhmeeConst.GetDbName(DbPrefixEnum.Vb, VesselId);
            string sqlNormalSuper = $"select 1 from {dbName}.wavedata_normal where pointid='{input.PointId}';";
            string sqlNormal = $"select *,chno,id,pointid from {dbName}.wdne_{input.PointFormatGuid()} where ts >= '{input.StartTime.PhmeeToUtcFormatDateTimeString()}' and ts < '{input.EndTime.AddSeconds(1).PhmeeToUtcFormatDateTimeString()}'  order by ts asc ;";
            List<WaveDataFeature> list = new List<WaveDataFeature>();

            using (TDengineConnection dbConnection = iTDConnectionFactory.GetConnection())
            {
                bool resultNormalFlag = true;
                using (DbCommand commandNormalExist = dbConnection.CreateCommand())
                {
                    commandNormalExist.CommandText = sqlNormalSuper;
                    var resultNormal = await commandNormalExist.ExecuteScalarAsync();
                    resultNormalFlag = Convert.ToBoolean(resultNormal);
                }
                if (resultNormalFlag)
                {
                    using (DbCommand commandNormal = dbConnection.CreateCommand())
                    {
                        commandNormal.CommandText = sqlNormal;
                        using (DbDataReader readerNormal = await commandNormal.ExecuteReaderAsync())
                        {
                            while (await readerNormal.ReadAsync())
                            {
                                WaveDataFeature waveDataFeatureNormal = new WaveDataFeature();
                                waveDataFeatureNormal.Type = ChartEnum.Normal;
                                waveDataFeatureNormal.TimeStamp = readerNormal.GetPhmeeTdEngineValue<DateTime>("ts");
                                waveDataFeatureNormal.AccRms = readerNormal.GetPhmeeTdEngineValue<float?>("acc_rms");
                                waveDataFeatureNormal.AccRmsWarning = readerNormal.GetPhmeeTdEngineValue<float?>("acc_rms_warning");
                                waveDataFeatureNormal.AccRmsAlarm = readerNormal.GetPhmeeTdEngineValue<float?>("acc_rms_alarm");
                                waveDataFeatureNormal.AccAvgPeak = readerNormal.GetPhmeeTdEngineValue<float?>("acc_avg_peak");
                                waveDataFeatureNormal.AccAvgPeakWarning = readerNormal.GetPhmeeTdEngineValue<float?>("acc_avg_peak_warning");
                                waveDataFeatureNormal.AccAvgPeakAlarm = readerNormal.GetPhmeeTdEngineValue<float?>("acc_avg_peak_alarm");
                                waveDataFeatureNormal.VelRms = readerNormal.GetPhmeeTdEngineValue<float?>("vel_rms");
                                waveDataFeatureNormal.VelRmsWarning = readerNormal.GetPhmeeTdEngineValue<float?>("vel_rms_warning");
                                waveDataFeatureNormal.VelRmsAlarm = readerNormal.GetPhmeeTdEngineValue<float?>("vel_rms_alarm");
                                waveDataFeatureNormal.AccEnvAvgPeak = readerNormal.GetPhmeeTdEngineValue<float?>("acc_env_avg_peak");
                                waveDataFeatureNormal.ChNo = readerNormal.GetPhmeeTdEngineValue<int>("chno");
                                waveDataFeatureNormal.Id = Guid.Parse(Encoding.UTF8.GetString(readerNormal.GetPhmeeTdEngineValue<byte[]>("id")));
                                waveDataFeatureNormal.PointId = Guid.Parse(Encoding.UTF8.GetString(readerNormal.GetPhmeeTdEngineValue<byte[]>("pointid")));
                                list.Add(waveDataFeatureNormal);
                            }
                        }
                    }
                }
            }

            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list;
        }

        /// <summary>
        /// 获取某个测点的TDEngine表源数据特征值-报警
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<List<WaveDataFeature>> GetTdEnginePointFeatureDataAlarm(Guid VesselId, ChartInputTrend input)
        {
            string dbName = PhmeeConst.GetDbName(DbPrefixEnum.Vb, VesselId);
            string sqlAlarmSuper = $"select 1 from {dbName}.wavedata_alarm where pointid='{input.PointId}';";
            string sqlAlarm = $"select *,chno,id,pointid from {dbName}.wdae_{input.PointFormatGuid()} where ts >= '{input.StartTime.PhmeeToUtcFormatDateTimeString()}' and ts < '{input.EndTime.AddSeconds(1).PhmeeToUtcFormatDateTimeString()}'  order by ts asc ;";

            List<WaveDataFeature> list = new List<WaveDataFeature>();

            using (TDengineConnection dbConnection = iTDConnectionFactory.GetConnection())
            {
                bool resultAlarmFlag = true;
                using (DbCommand commandAlarmExist = dbConnection.CreateCommand())
                {
                    commandAlarmExist.CommandText = sqlAlarmSuper;
                    var resultAlarm = await commandAlarmExist.ExecuteScalarAsync();
                    resultAlarmFlag = Convert.ToBoolean(resultAlarm);
                }
                if (resultAlarmFlag)
                {
                    using (DbCommand commandAlarm = dbConnection.CreateCommand())
                    {
                        commandAlarm.CommandText = sqlAlarm;
                        using (DbDataReader readerAlarm = await commandAlarm.ExecuteReaderAsync())
                        {
                            while (await readerAlarm.ReadAsync())
                            {
                                WaveDataFeature waveDataFeatureAlarm = new WaveDataFeature();
                                waveDataFeatureAlarm.Type = ChartEnum.Alarm;
                                waveDataFeatureAlarm.TimeStamp = readerAlarm.GetPhmeeTdEngineValue<DateTime>("ts");
                                waveDataFeatureAlarm.AccRms = readerAlarm.GetPhmeeTdEngineValue<float?>("acc_rms");
                                waveDataFeatureAlarm.AccRmsWarning = readerAlarm.GetPhmeeTdEngineValue<float?>("acc_rms_warning");
                                waveDataFeatureAlarm.AccRmsAlarm = readerAlarm.GetPhmeeTdEngineValue<float?>("acc_rms_alarm");
                                waveDataFeatureAlarm.AccAvgPeak = readerAlarm.GetPhmeeTdEngineValue<float?>("acc_avg_peak");
                                waveDataFeatureAlarm.AccAvgPeakWarning = readerAlarm.GetPhmeeTdEngineValue<float?>("acc_avg_peak_warning");
                                waveDataFeatureAlarm.AccAvgPeakAlarm = readerAlarm.GetPhmeeTdEngineValue<float?>("acc_avg_peak_alarm");
                                waveDataFeatureAlarm.VelRms = readerAlarm.GetPhmeeTdEngineValue<float?>("vel_rms");
                                waveDataFeatureAlarm.VelRmsWarning = readerAlarm.GetPhmeeTdEngineValue<float?>("vel_rms_warning");
                                waveDataFeatureAlarm.VelRmsAlarm = readerAlarm.GetPhmeeTdEngineValue<float?>("vel_rms_alarm");
                                waveDataFeatureAlarm.AccEnvAvgPeak = readerAlarm.GetPhmeeTdEngineValue<float?>("acc_env_avg_peak");
                                waveDataFeatureAlarm.AlarmLevel = readerAlarm.GetPhmeeTdEngineValue<int?>("alarm_level");
                                waveDataFeatureAlarm.ChNo = readerAlarm.GetPhmeeTdEngineValue<int>("chno");
                                waveDataFeatureAlarm.Id = Guid.Parse(Encoding.UTF8.GetString(readerAlarm.GetPhmeeTdEngineValue<byte[]>("id")));
                                waveDataFeatureAlarm.PointId = Guid.Parse(Encoding.UTF8.GetString(readerAlarm.GetPhmeeTdEngineValue<byte[]>("pointid")));
                                list.Add(waveDataFeatureAlarm);
                            }
                        }
                    }

                }

            }

            list = list.OrderBy(item => item.TimeStamp).ToList();

            return list;
        }

        #endregion

        #endregion
    }
}
